package MT::Template::Layouts::Tags;
use strict;

if (MT->version_number < 4) {
    require MT::Template::Context;
    MT::Template::Context->add_container_tag(Invoke         => \&invoke);
    MT::Template::Context->add_container_tag(InvokeTag      => \&tag);
    MT::Template::Context->add_container_tag(InvokeContents => \&contents);
    MT::Template::Context->add_container_tag(InvokeSetArg   => \&set_arg);
    MT::Template::Context->add_tag(LayoutArgument => \&arg);
    MT::Template::Context->add_conditional_tag(IfLayoutArgument => \&if_arg);
    MT::Template::Context->add_conditional_tag(
                                          UnlessLayoutArgument => \&unless_arg);
}

sub invoke {
    my ($ctx, $args, $cond) = @_;
    my $tag = $args->{tag}
      and delete $args->{tag};    # move tag arg to its special place
    $tag = lc $tag unless MT->version_number < 4;
    if (my $pass = $args->{pass_thru}) {
        delete $args->{pass_thru};
        $pass =~ s{^\s+|\s$}{}g;
        my $layout_args = $ctx->stash('MT::Plugin::TemplateLayout::args') || {};
        map { $args->{$_} = $layout_args->{$_} }
          grep { defined $layout_args->{$_} } split(/[\s,]+/, $pass);
    }
    my $invoke = {args => \%$args, tag => $tag};    # clone and stash args
    local $ctx->{__stash}{'MT::Plugin::Invoke'} = $invoke;
    my $builder = $ctx->stash('builder');
    my $tokens  = $ctx->stash('tokens');
    defined $builder->build($ctx, $tokens, $cond)
      or return $ctx->error($builder->errstr);
    $tag = $invoke->{tag}
      or
      return $ctx->error("MTInvoke requires a 'tag' attribute or MTInvokeTag.");
    $tag =~ s{^mt:?}{}i;
    my @invoke_tokens = ($tag, $invoke->{args}, $invoke->{tokens});
    defined(my $out = $builder->build($ctx, [\@invoke_tokens], $cond))
      or return $ctx->error($builder->errstr);
    $out;
}

sub tag {
    my ($ctx, $args, $cond) = @_;
    my $invoke  = get_invoke(@_) or return;
    my $builder = $ctx->stash('builder');
    my $tokens  = $ctx->stash('tokens');
    defined(my $tag = $builder->build($ctx, $tokens, $cond))
      or return $ctx->error($builder->errstr);
    $tag =~ s{^mt:?}{}i;
    $tag = lc $tag unless MT->version_number < 4;
    $invoke->{tag} = $tag;
    return '';
}

sub contents {
    my ($ctx) = @_;
    my $invoke = get_invoke(@_) or return;
    $invoke->{tokens} = $ctx->stash('tokens');
    return '';
}

sub set_arg {
    my ($ctx, $args, $cond) = @_;
    my $invoke = get_invoke(@_) or return;
    my $name = get_name(@_);
    return unless defined $name;
    my $builder = $ctx->stash('builder');
    my $tokens  = $ctx->stash('tokens');
    defined(my $tag = $builder->build($ctx, $tokens, $cond))
      or return $ctx->error($builder->errstr);
    $invoke->{args}->{$name} = $tag;
    return '';
}

sub arg {
    my ($ctx, $args, $cond) = @_;
    my $name = get_name(@_);
    return unless defined $name;
    $ctx->stash('MT::Plugin::TemplateLayout::args')->{$name} || '';
}

sub if_arg {
    my ($ctx, $args, $cond) = @_;
    my $name = get_name(@_);
    return 0 unless defined $name;
    my $arg = $ctx->stash('MT::Plugin::TemplateLayout::args')->{$name};
    return defined $arg if $args->{defined};
    return 0 unless defined $arg;
    foreach my $op (qw( eq ne lt gt le ge )) {
        if (defined(my $val = $args->{$op})) {
            return eval "'$arg' $op '$val'" || 0;
        }
    }
    $arg;
}

sub unless_arg { !if_arg(@_) }

#--- utility

sub get_invoke {
    $_[0]->stash('MT::Plugin::Invoke')
      or
      $_[0]->error(MT->translate('MT[_1] was not used in the proper context.'));
}

sub get_name {
    defined $_[1]->{name}
      ? $_[1]->{name}
      : $_[0]->error(
                     MT->translate(
                                   "'name' is a required attribute of MT[_1].",
                                   $_[0]->stash('tag')
                     )
      );
}

1;
